/******************************************************************* DetachWindow.c Does detach itself from the starting process and open a simple window with some easy gadgets. To do this detaching we need 2 functions more and since I want not change our ModuleEntry.c for this, I must name the first function OwnWindow(). You may also refer to the IconClock module of the SDK for an other example. Use ARTM, SnoopDos or similar if you want to check, that really an own process is running... *********************************************************************/ #define PARENT #include "/includes/Window.h" // now we need some other variables than in our structure // WindowHandle... typedef struct _PassingData { ULONG a4; // to store a4 (module is a4 relative) struct Library *library; // to store a pointer to dopus5.library struct Library *module; // to store a pointer to this module IPCData *ipc; // to store our NEW handle char args[256]; // since we want to use the args in our // detached process, we have to copy it struct Screen *screen; } PassingData; /********************************************************************/ // locale prototypes ULONG __asm __saveds New_Proc_Startup( register __a0 IPCData *ipc, register __a1 PassingData *pd ); void __saveds New_Proc( void ); BOOL OpenDOpusWin( WindowHandle *wh ); // function not changed BOOL HandleWindow( WindowHandle *wh ); // function not changed /********************************************************************/ // this is not the same function like before ! // it is the first special function we need... void OwnWindow( STRPTR args, struct Screen *screen ) { IPCData *new_proc = NULL; PassingData *pd; if( (pd = AllocMemH(mempool, sizeof(PassingData))) ) // allocate some memory { pd->screen = screen; // store the screen pointer strcpy( pd->args, args ); // store our arguments // now some special stuff, but everything is needed here... pd->a4 = getreg( REG_A4 ); pd->module = (struct Library *) getreg( REG_A6 ); pd->library = DOpusBase; // now we are ready to call IPC_Launch() IPC_Launch( 0, &new_proc, // pointer to pointer to the IPC of the new process, for storing... "ExampleWindow", // name of the new process (ULONG) New_Proc, // entrypoint of the new process 4096, // stack to use (ULONG) pd, // data to pass to the new process DOSBase ); // pointer to dos.library if( !new_proc ) // if detaching failed... FreeMemH( pd ); } } // let's do now the second special function ULONG __asm __saveds New_Proc_Startup( register __a0 IPCData *ipc, register __a1 PassingData *pd ) { // you may use this function also to setup things for your // main process, but you should not call any IPC functions here ! // we do only the minimum required..., but you will get some small // warnings from your compiler. Just ignore them now - they does // not appear, if we would do here some more things... struct Library *DOpusBase; // fix A4 putreg( REG_A4, pd->a4 ); // store IPC pointer pd->ipc = ipc; // get dopus.library - one warning now DOpusBase = pd->library; // now may follow your initialization // if something fails and you must quit, you should do: // return FALSE; // increase our library counter, so we can not be flushed // do not forget to decrease it, if your detached process ends pd->module->lib_OpenCnt++; return TRUE; // all was successfully } void __saveds New_Proc( void ) { // this is now just the same like until now our OwnWindow() function WindowHandle *wh; PassingData *pd; STRPTR args; IPCData *ipc; struct Library *DOpusBase; // but we must do some additional things // get dopus library if( !(DOpusBase = (struct Library *) FindName(&((struct ExecBase *)*((ULONG *)4))->LibList, "dopus5.library")) ) return; // do startup ipc = IPC_ProcStartup( (ULONG *) &pd, New_Proc_Startup ); // fix A4 so we can access global data in the module (eg library bases) putreg( REG_A4, pd->a4 ); // something failed until now ? if( !ipc ) { if( pd ) { IPC_Free( pd->ipc ); // possible it has a value here FreeMemH( pd ); // free our memory } return; } if( (wh = AllocMemH(mempool, sizeof(WindowHandle))) ) // allocate some memory { // we copy now our values, if you allocate for launching the real // structure you need, you must not do this of course... :) wh->screen = pd->screen; // store the screen pointer strncpy( wh->buffer, pd->args, 30 ); // copy our args - limited through our size of wh->buffer... wh->buffer[30] = NULL; // terminate our string args = wh->buffer; // now we can free our PassingData... FreeMemH( pd ); // now it is really the same excluding the end ... if( OpenDOpusWin(wh) ) // open the window { // we copy now the arguments into the text gadget // if we have supplied some... SetGadgetValue( wh->olist, GADGET_ID_TEXT, (ULONG) args ); while( TRUE ) { // I use here Wait(), so it is easier with the changes wh->signals = Wait( 1 << wh->win->UserPort->mp_SigBit ); // wait for window events if( wh->signals & 1 << wh->win->UserPort->mp_SigBit ) if( HandleWindow(wh) ) break; // does end the while loop } CloseConfigWindow( wh->win ); } FreeMemH( wh ); // free our memory } // since we are here a detached process, we must do some other cleanup too IPC_Free( ipc ); // and decrease our Library access counter, since we have increased it before ( (struct Library *) getreg(REG_A6) )->lib_OpenCnt--; } /********************************************************************/ // This function does open our window. We could have done this in the // function OwnWindow() too, but we need this function later again. BOOL OpenDOpusWin( WindowHandle *wh ) { NewConfigWindow ncfgwin; // we need a NewConfigWindow structure too // of couse you could also allocate it with // AllocMemH()... // and have to fill it ncfgwin.nw_Parent = wh->screen; // open on this screen // getting a localized title... ncfgwin.nw_Title = DOpusGetString( locale, MSG_WINDOW_TITLE ); ncfgwin.nw_Dims = &cfgwin; // a pointer to the ConfigWin structure ncfgwin.nw_Locale = locale; // the module locale pointer (from modinit.c) ncfgwin.nw_Port = NULL; // we doesn't supply a port ncfgwin.nw_Font = NULL; // just taking the screen font ncfgwin.nw_Flags = WINDOW_REQ_FILL | // fill with stripple pattern WINDOW_AUTO_KEYS | // handle keys automatic WINDOW_SCREEN_PARENT; // nw_Parent points to a screen if( (wh->win = OpenConfigWindow(&ncfgwin)) ) // open the window { if( (wh->olist = AddObjectList(wh->win, odef)) ) // add the gadgets return TRUE; CloseConfigWindow( wh->win ); // in error case do not forget :-) } return FALSE; } /********************************************************************/ // we does only close the window, if the closegadget was pressed // if you want to close it within a gadget, you must only in the // right case set "stop" to TRUE BOOL HandleWindow( WindowHandle *wh ) { BOOL stop = FALSE; ULONG value; while( !stop && (wh->imsg = GetWindowMsg(wh->win->UserPort)) ) { switch( wh->imsg->Class ) // let's handle the IDCMP { case IDCMP_GADGETUP: switch( GET_ID(wh->imsg) ) { case GADGET_ID_CYCLE: // we copy simply the same text to the text gadget value = GetGadgetValue( wh->olist, GADGET_ID_CYCLE ) + MSG_CLICK_ME; SetGadgetValue( wh->olist, GADGET_ID_TEXT, (ULONG) DOpusGetString(locale, value) ); break; case GADGET_ID_OKAY: // doing a message SetGadgetValue( wh->olist, GADGET_ID_TEXT, (ULONG) DOpusGetString(locale, MSG_OKAY_DONE) ); break; case GADGET_ID_CANCEL: SetGadgetValue( wh->olist, GADGET_ID_TEXT, (ULONG) DOpusGetString(locale, MSG_CANCEL_DONE) ); break; } break; case IDCMP_CLOSEWINDOW: // we can not simply return here, the IntuiMessage must replied first stop = TRUE; break; } ReplyWindowMsg( wh->imsg ); // remember: You should not use any other routines // to get/reply the messages of this window than // GetWindowMsg() and ReplyWindowMsg() !! } return stop; }